查看原文
其他

Spring Bean的加载深度解析

孙亮亮 SpringForAll社区 2021-05-26

1、getBean()

这个方法有点长我们进行分段解析。

1.1、从缓存获取

1//提取对应的beanName
2final String beanName = transformedBeanName(name);
3Object bean;
4
5// Eagerly check singleton cache for manually registered singletons.
6/**
7 * 检查缓存中或者实例工厂中是否有对应实例
8 * 为何会首先使用这段代码
9 * 因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖
10 * Spring创建Bean的原则是不等bean创建完成就会将创建Bean的ObjectFactory提早曝光
11 * 也就是讲ObjectFactory加入到缓存中,一旦下一个bean创建的时候需要依赖上个bean则直接使用ObjectFactory
12 */

13//尝试从混成或者singletonFactories中的ObjectFactory中获取
14Object sharedInstance = getSingleton(beanName);
15if (sharedInstance != null && args == null) {
16    if (logger.isDebugEnabled()) {
17        if (isSingletonCurrentlyInCreation(beanName)) {
18            logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
19                    "' that is not fully initialized yet - a consequence of a circular reference");
20        }
21        else {
22            logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
23        }
24    }
25
26    bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
27}

这个方法首先从缓存中去获取,这个时候缓存中当然没有数据,因为此时是初始化,我们还没有将bean方到singletonObjects这个map中去,如下图代码。

1.1.1、getSingleton()
1@Nullable
2protected Object getSingleton(String beanName, boolean allowEarlyReference) {
3    //检查缓存中是否存在实例
4    Object singletonObject = this.singletonObjects.get(beanName);
5    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
6        //若不存在则锁定全局变量进行处理
7        synchronized (this.singletonObjects) {
8            singletonObject = this.earlySingletonObjects.get(beanName);
9            if (singletonObject == null && allowEarlyReference) {
10                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
11                if (singletonFactory != null) {
12                    //调用预先设定的getObject方法
13                    singletonObject = singletonFactory.getObject();
14                    //记录在缓存中,earlySingletonObjects和singletonFactories互斥
15                    this.earlySingletonObjects.put(beanName, singletonObject);
16                    this.singletonFactories.remove(beanName);
17                }
18            }
19        }
20    }
21    return (singletonObject != NULL_OBJECT ? singletonObject : null);
22}

1.2、获取BEANFACOTRY

1if (isPrototypeCurrentlyInCreation(beanName)) {
2    throw new BeanCurrentlyInCreationException(beanName);
3}
4
5// Check if bean definition exists in this factory.
6//如果beaDefinitionMap中也就是在所有已经加载的类中不包括beanName则尝试从parentBeanFactory中检测
7BeanFactory parentBeanFactory = getParentBeanFactory();
8if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
9    // Not found -> check parent.
10    String nameToLookup = originalBeanName(name);
11    if (parentBeanFactory instanceof AbstractBeanFactory) {
12        return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
13                nameToLookup, requiredType, args, typeCheckOnly);
14    }
15    else if (args != null) {
16        //递归到BeanFactory中去寻找
17        // Delegation to parent with explicit args.
18        return (T) parentBeanFactory.getBean(nameToLookup, args);
19    }
20    else {
21        // No args -> delegate to standard getBean method.
22        return parentBeanFactory.getBean(nameToLookup, requiredType);
23    }
24}

这段代码首先获取该bean的父类,若有父类则用父类去实例化该bean,这里的parentBeanFactory为null,暂时不做考虑。接下来看第三部分。

1.3

1//如果不是做类型检查则是创建bean,这里要进行记录
2//第一部分
3if (!typeCheckOnly) {
4    markBeanAsCreated(beanName);
5}
6//第二部分
7try {
8    final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
9    checkMergedBeanDefinition(mbd, beanName, args);
10
11    // Guarantee initialization of beans that the current bean depends on.
12    String[] dependsOn = mbd.getDependsOn();
13    //若存在依赖则需要递归实例化依赖的bean
14    if (dependsOn != null) {
15        for (String dep : dependsOn) {
16            if (isDependent(beanName, dep)) {
17                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
18                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
19            }
20            registerDependentBean(dep, beanName);
21            getBean(dep);
22        }
23    }
24//第三部分
25    // Create bean instance.
26    //实例化依赖的bean之后可以实例化mbd本身了
27    //单例模式的创建
28    if (mbd.isSingleton()) {
29        sharedInstance = getSingleton(beanName, () -> {
30            try {
31                /**
32                 *核心创建bean
33                 */

34                return createBean(beanName, mbd, args);
35            }
36            catch (BeansException ex) {
37                // Explicitly remove instance from singleton cache: It might have been put there
38                // eagerly by the creation process, to allow for circular reference resolution.
39                // Also remove any beans that received a temporary reference to the bean.
40                destroySingleton(beanName);
41                throw ex;
42            }
43        });
44        //真正的bean初始化处理
45        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
46    }
  • 1、第一部分,标记目前的bean属于正在创建状态

  • 2、第二部分,根据beanName获取该bean在beanFactory中的beanDefinitionMap中beanDefinition,然后获取该bean所依赖的bean(此处是spring解决循环依赖的关键),如果依赖的bean还未创建,则先创建依赖的bean,依次递归调用(DI依赖注入的概念),如果找不到依赖,则忽略。

  • 3、若是单例,创建bean,调用CreateBean()方法,此处只考虑单例模式

接下来跟踪createBean()方法。此处调用的是AbstractAutowireCapableBeanFactory中的方法

1.4、CREATEBEAN()

1//第一部分
2if (logger.isDebugEnabled()) {
3    logger.debug("Creating instance of bean '" + beanName + "'");
4}
5RootBeanDefinition mbdToUse = mbd;
6
7// Make sure bean class is actually resolved at this point, and
8// clone the bean definition in case of a dynamically resolved Class
9// which cannot be stored in the shared merged bean definition.
10/**
11 * 锁定class,根据设置的class属性或者根据classname来解析class
12 */

13Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
14if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
15    mbdToUse = new RootBeanDefinition(mbd);
16    mbdToUse.setBeanClass(resolvedClass);
17}
18//第二部分
19//验证及准备覆盖的方法
20try {
21    mbdToUse.prepareMethodOverrides();
22}
23catch (BeanDefinitionValidationException ex) {
24    throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
25            beanName, "Validation of method overrides failed", ex);
26}
27//第三部分
28try {
29    // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
30    //给BeanPostProcessors一个机会来返回代理来代替真正的实例,前置处理器
31    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
32    /**
33     * 前置处理后返回结果不为空,直接返回结果,AOP功能就是基于这里判断的
34     */

35    if (bean != null) {
36        return bean;
37    }
38}
39catch (Throwable ex) {
40    throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
41            "BeanPostProcessor before instantiation of bean failed", ex);
42}
43//第四部分
44try {
45    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
46    if (logger.isDebugEnabled()) {
47        logger.debug("Finished creating instance of bean '" + beanName + "'");
48    }
49    return beanInstance;
50}
  • 1、第一部分:确保该bean的class是真实存在的,也就是该bean是可以classload可以找到加载的,若不存在则放入beanDefination中

  • 2、第二部分:准备方法的重写

  • 3、第三部分:(重要)最后的return就是返回的bean,但看注释:Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.这边就很清晰了,我们以前在beanPostProcessor的章节讲过,beanPostProcessor是可以临时修改bean的,它的优先级高于正常实例化bean的(也就是第四部分实例化的方法)如果beanPostProcessor能返回,则直接返回了,这边代码下次分析,我们还是先分析主要流程:

  • 4、doCreateBean(beanName, mbd, args)这个方法,接下来看这个

    1BeanWrapper instanceWrapper = null;
    2if (mbd.isSingleton()) {
    3  instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    4}
    5if (instanceWrapper == null) {
    6  //根据指定的bean使用对应的侧脸创建新的实例,如工厂方法,构造函数自动注入,简单初始化
    7  instanceWrapper = createBeanInstance(beanName, mbd, args);
    8}
    9final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
    10Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
    11mbd.resolvedTargetType = beanType;
    12
    13if (beanType != null) {
    14  // Allow post-processors to modify the merged bean definition.
    15  synchronized (mbd.postProcessingLock) {
    16      if (!mbd.postProcessed) {
    17          try {
    18              applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    19          }
    20          catch (Throwable ex) {
    21              throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    22                      "Post-processing of merged bean definition failed", ex);
    23          }
    24          mbd.postProcessed = true;
    25      }
    26  }
    27}

这里首先初始化一个instanceWrapper,然后再看createBeanInstance()

1protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
2    // Make sure bean class is actually resolved at this point.
3    Class<?> beanClass = resolveBeanClass(mbd, beanName);
4
5    if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
6        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
7                "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
8    }
9
10    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
11    if (instanceSupplier != null) {
12        return obtainFromSupplier(instanceSupplier, beanName);
13    }
14
15    if (mbd.getFactoryMethodName() != null)  {
16        return instantiateUsingFactoryMethod(beanName, mbd, args);
17    }
18
19    // Shortcut when re-creating the same bean...
20    boolean resolved = false;
21    boolean autowireNecessary = false;
22    if (args == null) {
23        synchronized (mbd.constructorArgumentLock) {
24            if (mbd.resolvedConstructorOrFactoryMethod != null) {
25                resolved = true;
26                autowireNecessary = mbd.constructorArgumentsResolved;
27            }
28        }
29    }
30    if (resolved) {
31        if (autowireNecessary) {
32            return autowireConstructor(beanName, mbd, nullnull);
33        }
34        else {
35            return instantiateBean(beanName, mbd);
36        }
37    }
38
39    // Need to determine the constructor...
40    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
41    if (ctors != null ||
42            mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
43            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
44        return autowireConstructor(beanName, mbd, ctors, args);
45    }
46
47    // No special handling: simply use no-arg constructor.
48    return instantiateBean(beanName, mbd);
49}

这块代码主要是再次对bean做安全检查并确定该bean有默认的构造函数,createBeanInstance()这个方法最后一行

1protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
2    try {
3        Object beanInstance;
4        final BeanFactory parent = this;
5        if (System.getSecurityManager() != null) {
6            beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
7                    getInstantiationStrategy().instantiate(mbd, beanName, parent),
8                    getAccessControlContext());
9        }
10        else {
11            beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
12        }
13        BeanWrapper bw = new BeanWrapperImpl(beanInstance);
14        initBeanWrapper(bw);
15        return bw;
16    }
17    catch (Throwable ex) {
18        throw new BeanCreationException(
19                mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
20    }
21}

然后我们再回到doCreateBean()这个方法,在AbstractAutowireCapableBeanFactory

1// Initialize the bean instance.
2Object exposedObject = bean;
3try {
4    //对bean进行填充,将各个属性值注入,其中,可能存在依赖与其他bean的属性,则会递归初始依赖bean
5    populateBean(beanName, mbd, instanceWrapper);// sunliang marked
6    if (exposedObject != null) {
7        //调用初始化方法,比如init-method
8        exposedObject = initializeBean(beanName, exposedObject, mbd);
9    }
10}

初始化bean,的确,现在bean已经实例化了,开始初始化该bean,进入initializeBean(…)这个方法

1if (System.getSecurityManager() != null) {
2    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
3        invokeAwareMethods(beanName, bean);
4        return null;
5    }, getAccessControlContext());
6}
7else {
8    invokeAwareMethods(beanName, bean);
9}

接下来进入到invokeAwareMethods()方法

1private void invokeAwareMethods(final String beanName, final Object bean) {
2    if (bean instanceof Aware) {
3        if (bean instanceof BeanNameAware) {
4            ((BeanNameAware) bean).setBeanName(beanName);
5        }
6        if (bean instanceof BeanClassLoaderAware) {
7            ClassLoader bcl = getBeanClassLoader();
8            if (bcl != null) {
9                ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
10            }
11        }
12        if (bean instanceof BeanFactoryAware) {
13            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
14        }
15    }
16}

再回到initializeBean()方法中

1try {
2    invokeInitMethods(beanName, wrappedBean, mbd);
3}
4protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
5        throws Throwable 
{
6
7    boolean isInitializingBean = (bean instanceof InitializingBean);
8    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
9        if (logger.isDebugEnabled()) {
10            logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
11        }
12        if (System.getSecurityManager() != null) {
13            try {
14                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
15                    ((InitializingBean) bean).afterPropertiesSet();
16                    return null;
17                }, getAccessControlContext());
18            }
19            catch (PrivilegedActionException pae) {
20                throw pae.getException();
21            }
22        }
23        else {
24        //第一部分
25            ((InitializingBean) bean).afterPropertiesSet();
26        }
27    }
28
29    if (mbd != null) {
30        String initMethodName = mbd.getInitMethodName();
31        if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
32                !mbd.isExternallyManagedInitMethod(initMethodName)) {
33                //第二部分
34            invokeCustomInitMethod(beanName, bean, mbd);
35        }
36    }
37}

首先先判断该bean是否实现了InitializingBean,如果实现了先执行afterPropertiesSet这个方法,然后如果该bean又执行了init-method,到此我们的bean创建和加载算是基本完成,下一节分析一些具体详细点的实现。



限时扫码关注领取600页+Spring官方教程小书


  1. 限时3周免费下载

  2. 长按识别二维码关注SpringForAll社区公众号

  3. 在公众号回复“Spring”或者"spring"即可获取



点击原文阅读更多


推荐:给大家推荐8个SpringBoot精选项目

上一篇:Scala语言概述

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存